class ContestsController < ApplicationController
  before_filter :store_location
  before_filter :login_required, :except => [:show, :index, :board, :offline_board]
  before_filter :process_problem_difficulties, :only => [:new, :create]
#  before_filter :validate_ajax_request,
#    :only => [:add_difficulty, :add_problem, :remove_problem, :query]
  
  def authorized?
    admin?
  end
  
  def index
    if params[:filter] == "active"
      @contests = Contest.find(:all, 
        :conditions =>["start_time <= ? AND end_time >= ?", Time.now.utc, Time.now.utc],
        :order => 'start_time DESC')
      if(@contests.size() == 0)
        @start_time = Contest.find(:first, :conditions =>["start_time > ?", Time.now.utc],
            :select => "start_time", :order => "start_time asc")
        @time_to_next = @start_time.start_time - Time.now.utc unless @start_time.nil?
        #@time_to_next = @time_to_next.time_left unless @time_to_next.nil?
        render :file => "#{RAILS_ROOT}/app/views/contests/no_active.html.erb", :layout=> "application"
      else
        render :file => "#{RAILS_ROOT}/app/views/contests/index.html.erb", :layout=> "application"
      end
    else
      if admin?
         @contests = Contest.find(:all, :order => 'start_time DESC')
      else
         @contests = Contest.find(:all, :conditions =>["start_time <= ?", Time.now.utc], :order => 'start_time DESC')
      end
    end
    
  end

  def board
    @contest = Contest.find(params[:id])
    @contest_runs = @contest.problems.inject([]){|acc, val| acc + val.runs}
    @contest_runs = @contest_runs.select{|r| !(r.status.nil?) && r.created_at >= @contest.start_time && r.created_at <= @contest.end_time}
    @contest_users = @contest_runs.inject([]){|acc, val| acc << val.user}.uniq
  end
  
  def offline_board
    @contest = Contest.find(params[:id])
    @contest_runs = @contest.problems.inject([]){|acc, val| acc + val.runs}
    @contest_runs = @contest_runs.select{|r| !(r.status.nil?) && r.created_at >= @contest.start_time}
    @contest_users = @contest_runs.inject([]){|acc, val| acc << val.user}.uniq
  end
  
  def new
    @contest = Contest.new
    #@contest.start_time = Time.now.localtime
    #@contest.end_time = Time.now.localtime
  end
  
  def show
    @contest = Contest.find(params[:id])
    @selected_problems = @contest.problems
  end

  def create
    @contest = Contest.new(params[:contest])

    if @contest.save
      pdiff = Hash.new{|hash, key| hash[key] = 0}
      @problem_difficulties.each {|_, v| pdiff[v.to_i] += 1}
      @contest.problems = ContestsHelper::choose_problems(pdiff)

      flash[:notice] = 'Contest was successfully created.'
      redirect_to(@contest)
    else
      render :action => "new"
    end
  end

  def destroy
    @contest = Contest.find(params[:id])
    @contest.destroy
    
    redirect_to(contests_url)
  end

  def edit
    @found = false
    @results = Array.new
    @contest = Contest.find(params[:id])
  end

  def update
    @found = false
    @results = Array.new
    @contest = Contest.find(params[:id])

    if @contest.update_attributes(params[:contest])
      flash[:notice] = 'Contest was successfully updated.'
      redirect_to(@contest)
    else
      render :action => "edit"
    end
  end

  def add_difficulty
    @difficulty_index = params[:difficulty_index]
  end

  def remove_difficulty
    render :text => ""
  end

  def remove_problem
    if (params[:id] and params[:problem_id])
      contest = Contest.find(:first, :conditions => {:id => params[:id]})
      problem = Problem.find(:first, :conditions => {:id => params[:problem_id]})
      if contest and problem
        contest.problems.delete problem
      end
    end
    render :text => ""
  end

  def query
    max = 10
    if params[:query] and params[:query] != ""
      selected = 0
      # TODO: can optimise
      @results = Problem.find(:all).select do |p|
        selected < max and p.name.include?(params[:query]) and selected += 1
      end

      @found = (@results and @results[0].name == params[:query])
    else
      @results = Array.new
      @found = false
    end
  end

  def add_problem
    @added = false
    if params[:id]
      @contest = Contest.find(:first, :conditions => {:id => params[:id]})
      @problem = nil
      if params[:problem_id]
        @problem = Problem.find(:first, :conditions => {:id => params[:problem_id]})
      elsif params[:difficulty]
        problems = ContestsHelper::choose_problems({params[:difficulty].to_i => 1}, @contest.problems)
        @problem = problems[0] if problems and problems.size > 0
      end
      if @contest and @problem and !(@contest.problems.include? @problem)
        # add method addProblem in model
        @contest.problems << @problem
        @added = true
      end
    end
  end

  protected
  def process_problem_difficulties
    @problem_difficulties = params.select do |k, v|
      k.to_s =~ /difficulty\d/ and (1..5).include?(v.to_i)
    end.sort do |a, b|
      a[0].to_s <=> b[0].to_s
    end
    @difficulty_index = (@problem_difficulties.map  do |k, _|
        k.to_s.split(/[A-Za-z]*/)[1].to_i
      end << -1).max + 1
  end

  def validate_ajax_request
    if !request.xml_http_request?
      p "Bad"
      redirect_to :action => "index"
    end
  end

  def check
    p "post #{request.post?}"
    p "get #{request.get?}"
  end
end

